Experimental Manuals FII-PRA040 FPGA Board Based FPGA Tutor Risc-V

Learn HDMI principle, Introduction to HDMI and ADV7511 Chip, HDMI Display, FII-PRA040 Altera Risc-V tutorial Experiment 13

Experiment 13 HDMI Display

13.1 Experiment Objective

  1. Review IIC protocol
  2. Review EEPROM read and write
  3. Learn HDMI principle

13.2 Experiment Implement

Display different image content on the screen through the HDMI.

13.3 Experiment

13.3.1 Introduction to HDMI and ADV7511 Chip

Image display processing has always been the focus of FPGA research. At present, the image display mode is also developing. The image display interface is also gradually transitioning from the old VGA interface to the new DVI or HDMI interface. HDMI (High Definition Multimedia Interface) is a digital video/audio interface technology. It is a dedicated digital interface for image transmission. It can transmit audio and video signals at the same time.

The ADV7511 is a chip that converts FPGA digital signal to HDMI signal following VESA standard. For more details, see the related chip manual. Among them, “ADV7511 Programming Guide” and “ADV7511 Hardware Users Guide” are the most important. The registers of the ADV7511 can be configured by referring those documents.

ADV7511 Register Configuration Description: The bus inputs D0-D3, D12-D15, and D24-D27 of the ADV7511 have no input, and each bit of data is in 8-bit mode. Directly set 0x15 [3:0]) 0x0 data, 0x16 [3:2] data does not need to be set for its mode. Set [5:4] of 0X16 to 11for 8-bit data and keep the default values ​​for the other digits. 0x17[1] refers to the ratio of the length to the width of the image. It can be set to 0 or 1. The actual LCD screen will not change according to the data but will automatically stretch the full screen mode according to the LCD’s own settings. 0x18[7] is the way to start the color range stretching. The design is that RGB maps directly to RGB, so it can be disabled directly. 0X18[6:5] is also invalid currently. 0XAF [1] is to set HDMI or DVI mode, the most direct point of HDMI than DVI is that HDMI can send digital audio data and encrypted data content. This experiment only needs to Display the picture, and it can be set directly to DVI mode. Set 0XAF [7] to 0 to turn off HDMI encryption. Due to GCCD, deep color encryption data is not applicable, so the GC option is turned off. 0x4c register does not need to be set as well. Other sound data setting can be ignored here for DVI output mode. After writing these registers, the image can be displayed successfully.

13.3.2 Hardware Design

The onboard HDMI module consists of an HDMI interface and an ADV7511 chip. The physical photo is shown in Figure 13.1. The schematics is shown in Figure 13.2.

HDMI interface and ADV7511 chip physical photo
HDMI interface and ADV7511 chip physical photo

Figure 13.1 HDMI interface and ADV7511 chip physical photo

Figure 13.2 Schematics of HDMI

ADV7511 chip is set through the IIC bus and send the picture information to be displayed to the chip through HDMI_D0 to HDMI_D23, and control signals HDMI_HSYNC and HDMI_VSYNC and the clock signal HDMI_CLK, which are transmitted to the PC through the HDMI interface after being processed internally by the chip.

13.3.3 Introduction to the Program

The configuration part of the ADV7511 chip is carried out using the IIC protocol, with reference to Experiment 11 and Experiment 12. A brief introduction to the data processing section is now available.

module hdmi_test (

input rst_n,

input clk_in,

input key1,

output vga_hs,

output vga_vs,

output [7:0] vga_r,

output [7:0] vga_g,

output [7:0] vga_b,

output vga_clk,

inout scl,

inout sda,

output en

);

The FPGA configures the ADV7511 chip through the IIC bus (clock line scl, data line sda). After the configuration is completed, the output image information needs to be determined. Taking the 1080P (1920*1080) image format as an example, it outputs data signal rgb_r (red component), rgb_g (green component), rgb_b (blue component), a line sync signal rgb_hs, a field sync signal rgb_vs, and a clock rgb_clk signal. Each pixel is formed by a combination of three color components. Each row of 1920 pixels is filled with color information in a certain order (from left to right) and begin to fill the next line after completing one line, in a certain order (from top to bottom) to finish 1080 lines, so that one frame of image information is completed. The image information of each frame is determined by this horizontal and vertical scanning, and then transmitted to the ADV7511 for processing. The timing diagram of the horizontal and vertical scan is shown in Figure 13.3, Figure 13.4.

Figure 13.3 Horizontal synchronization

Figure 13.4 Vertical synchronization

The second step: data definition of 1080p image timing generation

Horizontal line scan parameter setting 1920*1080 60 Hz clock 130 MHz

parameter LinePeriod = 2000; // Line period

parameter H_SyncPulse = 12; // Line sync pulse (Sync a)

parameter H_BackPorch = 40; // Display back edge (Back porch b)

parameter H_ActivePix = 1920; // Display interval c

parameter H_FrontPorch= 28; // Display front edge (Front porch d)

parameter Hde_start = 52;

parameter Hde_end = 1972;

Vertical scan parameter setting 1920*1080 60Hz

parameter FramePeriod = 1105; //Frame period

parameter V_SyncPulse = 4; // Vertical sync pulse (Sync o)

parameter V_BackPorch = 18; // Display trailing edge (Back porch p) parameter V_ActivePix = 1080; //Display interval q

parameter V_FrontPorch= 3; // Display front edge (Front porch r)

parameter Vde_start = 22;

parameter Vde_end = 1102;

reg [12:0] x_cnt;

reg [10:0] y_cnt;

reg [23:0] grid_data_1;

reg [23:0] grid_data_2;

reg [23:0] bar_data;

reg [3:0] rgb_dis_mode;

reg [7:0 ] rgb_r_reg;

reg [7:0] rgb_g_reg;

reg [7:0] rgb_b_reg;

reg hsync_r;

reg vsync_r;

reg hsync_de;

reg vsync_de;

reg [15:0] key1_counter; //Button

wire locked;

reg rst;

wire [12:0] bar_interval;

assign bar_interval = H_ActivePix[15: 3]; //Color strip width

The third step: Generate display content

always @ (posedge rgb_clk)

begin

if (rst)

hsync_r <= 1’b1;

else if (x_cnt == LinePeriod)

hsync_r <= 1’b0;

else if (x_cnt == H_SyncPulse)

hsync_r <= 1’b1;

if (rst)

hsync_de <= 1’b0;

else if (x_cnt == Hde_start)

hsync_de <= 1’b1;

else if (x_cnt == Hde_end)

hsync_de <= 1’b0;

end

always @ (posedge vga_clk)

begin

if (rst)

y_cnt <= 1’b1;

else if (x_cnt == LinePeriod) begin

if (y_cnt == FramePeriod)

y_cnt <= 1’b1;

else

y_cnt <= y_cnt + 1’b1;

end

end

always @ (posedge rgb_clk)

begin

if (rst)

vsync_r <= 1’b1;

else if ((y_cnt == FramePeriod) &(x_cnt == LinePeriod))

vsync_r <= 1’b0;

else if ((y_cnt == V_SyncPulse) &(x_cnt == LinePeriod))

vsync_r <= 1’b1;

if (rst)

vsync_de <= 1’b0;

else if ((y_cnt == Vde_start) & (x_cnt == LinePeriod))

vsync_de <= 1’b1;

else if ((y_cnt == Vde_end) & (x_cnt == LinePeriod))

vsync_de <= 1’b0;

end

assign en = hsync_de & vsync_de;

always @(posedge rgb_clk)

begin

if ((x_cnt[4]==1’b1) ^ (y_cnt[4]==1’b1))

grid_data_1 <= 24’h000000;

else

grid_data_1<= 24’hffffff;

if ((x_cnt[6] == 1’b1) ^ (y_cnt[6] == 1’b1))

grid_data_2 <=24’h000000;

else

grid_data_2 <=24’hffffff;

end

always @ (posedge rgb _clk)

begin

if (x_cnt==Hde_start)

bar_data <= 24’hff0000; // Red strip

else if (x_cnt == Hde_start + bar_interval)

bar_data <= 24’h00ff00; // Green strip

else if (x_cnt == Hde_start + bar_interval*2)

bar_data <= 24’h0000ff; // Blue strip

else if (x_cnt == Hde_start + bar_interval*3)

bar_data <= 24’hff00ff; // Purple strip

else if (x_cnt == Hde_start + bar_interval*4)

bar_data <= 24’hffff00; // Yellow strip

else if (x_cnt == Hde_start + bar_interval*5)

bar_data <= 24’h00ffff; // Light blue strip

else if (x_cnt == Hde_start + bar_interval*6)

bar_data <= 24’hffffff; // White strip

else if (x_cnt == Hde_start + bar_interval*7)

bar_data <= 24’hff8000; // Orange strip

else if (x_cnt == Hde_start + bar_interval*8)

bar_data <= 24’h000000; //Black strip

end

always @ (posedge vga_clk)

begin

if (rst) begin

rgb_r_reg <= 0;

rgb_g_reg <= 0;

rgb_b_reg <= 0;

end

else case (vga_dis_mode)

4’b0000 : // Display all black

begin

rgb_r_reg <= 0;

rgb_g_reg <= 0;

rgb_b_reg <= 0;

end

4’b0001 : // Display all white

begin

rgb_r_reg <= 8’hff;

rgb_g_reg <= 8’hff;

rgb_b_reg <= 8’hff;

end

4’b0010 : // Display all red

begin

rgb_r_reg <= 8’hff;

rgb_g_reg <= 0;

rgb_b_reg <= 0;

end

4’b0011 : // Display all green

begin

rgb_r_reg <= 0;

rgb_g_reg <= 8’hff;

rgb_b_reg <= 0;

end

4’b0100 : // Display all blue

begin

rgb_r_reg <= 0;

rgb_g_reg <= 0;

rgb_b_reg <= 8’hff;

end

4’b0101 : // Display square 1

begin

rgb_r_reg <= grid_data_1[23:16];

rgb_g_reg <= grid_data_1[15:8];

rgb_b_reg <= grid_data_1[7:0];

end

4’b0110 : // Display square 2

begin

rgb_r_reg <= grid_data_2[23:16];

rgb_g_reg <= grid_data_2[15:8];

rgb_b_reg <= grid_data_2[7:0];

end

4’b0111 : // Display horizontal gradient

begin

rgb_r_reg <= x_cnt[10:3];

rgb_g_reg <= x_cnt[10:3];

rgb_b_reg <= x_cnt[10:3];

end

4’b1000 : // Display vertical gradient

begin

rgb_r_reg <= y_cnt[10:3];

rgb_g_reg <= y_cnt[10:3];

rgb_b_reg <= y_cnt[10:3];

end

4’b1001 : // Display red horizontal gradient

begin

rgb_r_reg <= x_cnt[10:3];

rgb_g_reg <= 0;

rgb_b_reg <= 0;

end

4’b1010 : // Display green horizontal gradient

begin

rgb_r_reg <= 0;

rgb_g_reg <= x_cnt[10:3];

rgb_b_reg <= 0;

end

4’b1011 : // Display blue horizontal gradient

begin

rgb_r_reg <= 0;

rgb_g_reg <= 0;

rgb_b_reg <= x_cnt[10:3];

end

4’b1100 : // Display colorful strips

begin

rgb_r_reg <= bar_data[23:16];

rgb_g_reg <= bar_data[15:8];

rgb_b_reg <= bar_data[7:0];

end

default : // Display all white

begin

rgb_r_reg <= 8’hff;

rgb_g_reg <= 8’hff;

rgb_b_reg <= 8’hff;

end

endcase

end

assign rgb_hs = hsync_r;

assign rgb_vs = vsync_r;

assign rgb_r = (hsync_de & vsync_de) ? rgb_r_reg : 8’h00;

assign rgb_g = (hsync_de & vsync_de) ? rgb_g_reg : 8’b00;

assign rgb_b = (hsync_de & vsync_de) ? rgb_b_reg : 8’h00;

always @(posedge rgb_clk)

begin

if (key1 == 1’b1)

key1_counter <= 0;

else if ((key1 == 1’b0) & (key1_counter <= 16’d130000))

key1_counter <= key1_counter + 1’b1;

if (key1_counter == 16’h129999) begin

if(rgb_dis_mode == 4’b1100)

rgb_dis_mode <= 4’b0000;

else

rgb_dis_mode <= rgb_dis_mode + 1’b1;

end

end

When the button is pressed, a key1 signal will be input, and the content displayed on the screen will change according to the change of vga_dis_mode, and the corresponding picture content will be displayed.

13.4 Experiment Verification

The first step: pin assignment

Table 13.1 HDMI Experiment Pin Mapping

Signal Name Network Label FPGA Pin Port Description
clk CLK_50M G21 System clock 50 MHz
rst_n PB3 Y6 Reset
en HDMI_R_DE A8 Enable
scl I2C_SCL D13 IIC clock line
sda I2C_SDA C13 IIC data line
key1 PB2 V5 Switch display content
vga_clk HDMI_R_CLK E5 HDMI clock
vga_hs HDMI_R_HS B9 Horizontal sync signal
vg_vs HDMI_R_VS A9 Vertical sync signal
vga_b[0] HDMI_R_D0 A7 Blue output
vga_b[1] HDMI_R_D1 B8
vga_b[2] HDMI_R_D2 E9
vga_b[3] HDMI_R_D3 B7
vga_b[4] HDMI_R_D4 C8
vga_b[5] HDMI_R_D5 C6
vga_b[6] HDMI_R_D6 F8
vga_b[7] HDMI_R_D7 B6
vga_g[0] HDMI_R_D8 A5 Green output
vga_g[1] HDMI_R_D9 C7
vga_g[2] HDMI_R_D10 D7
vga_g[3] HDMI_R_D11 B5
vga_g[4] HDMI_R_D12 C6
vga_g[5] HDMI_R_D13 A4
vga_g[6] HDMI_R_D14 D6
vga_g[7] HDMI_R_D15 B4
vga_r[0] HDMI_R_D16 E7 Red output
vga_r[1] HDMI_R_D17 A3
vga_r[2] HDMI_R_D18 C4
vga_r[3] HDMI_R_D19 B3
vga_r[4] HDMI_R_D20 C3
vga_r[5] HDMI_R_D21 F7
vga_r[6] HDMI_R_D22 F9
vga_r[7] HDMI_R_D23 G7

The second step: board verification

After the pin assignment is completed, the compilation is performed, and the development board is programmed.

Press the push button and the display content changes accordingly. The experimental phenomenon is shown in the figure below (only a few are listed).

Figure 13.5 HDMI display (all white)

Figure 13.6 HDMI display (square)

Figure 13.7 HDMI display (color strip)

Related posts